import { Asset, AssetManager, assetManager, Prefab } from "cc";
import { LogMgr } from "../log/LogMgr";
import { ResourceNames } from "../../game/constant/CommonConstant";
import { DataCtx } from "../../game/data/DataCtx";

export default class AssetMgr{


    private static _instance: AssetMgr;
    public static get Ins():AssetMgr{
        if(!AssetMgr._instance){
            AssetMgr._instance = new AssetMgr();
        }
        return AssetMgr._instance;
    }

    public bundleCahche: Map<string, AssetManager.Bundle> = new Map();
    public prefabCahche: Map<string, Prefab> = new Map();

    /**
     * 加载bundle
     * @param url 
     * @returns 
     */
    public loadBundle(url: string): Promise<AssetManager.Bundle>{
        return new Promise((resolve, reject) => {
            if(this.bundleCahche.has(url)){
                return resolve(this.bundleCahche.get(url));
            }
            assetManager.loadBundle(url, (error,data)=>{
                if(error){
                    console.log("load bundle error:", url);
                    reject(null)
                }else{
                    LogMgr.debug("加载bundle成功:"+url)
                    this.bundleCahche.set(url, data);
                    resolve(data);
                }
            });
        });
    }
    loadConfigBundle():Promise<AssetManager.Bundle> {
        return new Promise((resolve,reject)=>{
            let bundle = this.loadBundle(ResourceNames.TableResources)
            bundle.then((bundle)=>{
                //全部load json文件
                let len = DataCtx.jsonFileNames.length
                let tt:Promise<any>[] = []
                for (let index = 0; index < len; index++) {
                    const element = DataCtx.jsonFileNames[index];
                    let task = new Promise((s,r)=>{
                        bundle.load(element,(erro)=>{
                            if(erro){
                                LogMgr.warn("配置文件加载失败："+element)
                                r("error")
                            }else{
                                s("ok")
                            }
                        })
                    })
                    tt.push(task)
                }
                Promise.all(tt).then(()=>{
                    resolve(bundle)
                }).catch(e=>reject(e))

            }).catch(e=>{
                reject(null)
            })
        })

    }

    /**
     * 根据资源路径和资源名加载资源
     * @param resouceName 
     * @param name 
     * @param type 
     * @returns 
     */
    loadAsset<T extends Asset>(resouceName:string,name: string,type:new (...args: any[]) => T): Promise<T> {
        return new Promise((resolve, reject) => {
            let bundle = this.bundleCahche.get(resouceName)
            if(bundle){
                bundle.load(name,type,(error, asset) => {
                    if(error) {
                        resolve(null);
                    }
                    if (asset) {
                        resolve(asset)
                    }
                })
            }else{
                 this.loadBundle(resouceName).then(d=>{
                    d.load(name,type,(error, asset) => {
                        if(error) {
                            LogMgr.err("加载资源budle 失败：",error)
                            resolve(null);
                        }
                        if (asset) {
                            resolve(asset)
                        }
                    })
                 })
            }
        });
    }
    
    /**
     * 从bundle中获取资源
     * @param resouceName 
     * @param name 
     * @param type 
     * @returns 
     */
    getBundleRes<T extends Asset>(resouceName:string,name: string,type:new (...args: any[]) => T):T {
        let bundle: AssetManager.Bundle = this.bundleCahche.get(resouceName);
        if (!bundle) {
            LogMgr.warn("分包:" + resouceName + "不存在");
            return null;
        }
        return bundle.get(name);
    }
    
    /**
     * 加载预制件
     * @param resouceName 
     * @param name 
     * @returns 
     */
    async loadPrefab(resouceName:string,name: string): Promise<Prefab> {
        if(this.prefabCahche.has(name)){
            return this.prefabCahche.get(name)
        }
        let prefab =await this.loadAsset(resouceName,name, Prefab)
        if(prefab && prefab instanceof Prefab){
            this.prefabCahche.set(name, prefab)
        }
        return prefab
    }
}